home *** CD-ROM | disk | FTP | other *** search
/ CU Amiga Super CD-ROM 17 / CU Amiga Magazine's Super CD-ROM 17 (1997)(EMAP Images)(GB)[!][issue 1997-12].iso / CUCD / Programming / Make / source / vmsify.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-08-27  |  15.3 KB  |  928 lines

  1. /*
  2.   vmsify.c
  3.  
  4.   Module for vms <-> unix file name conversion
  5.  
  6.   Written by Klaus Kämpf (kkaempf@progis.de)
  7.   of proGIS Software, Aachen, Germany
  8.  
  9. */
  10.  
  11. #include <string.h>
  12. #include <ctype.h>
  13.  
  14. #if VMS
  15. #include <unixlib.h>
  16. #include <stdlib.h>
  17. #include <jpidef.h>
  18. #include <descrip.h>
  19. #include <uaidef.h>
  20. #include <ssdef.h>
  21. #include <starlet.h>
  22. #include <lib$routines.h>
  23. /* Initialize a string descriptor (struct dsc$descriptor_s) for an
  24.    arbitrary string.   ADDR is a pointer to the first character
  25.    of the string, and LEN is the length of the string. */
  26.  
  27. #define INIT_DSC_S(dsc, addr, len) do { \
  28.   (dsc).dsc$b_dtype = DSC$K_DTYPE_T;    \
  29.   (dsc).dsc$b_class = DSC$K_CLASS_S;    \
  30.   (dsc).dsc$w_length = (len);           \
  31.   (dsc).dsc$a_pointer = (addr);         \
  32. } while (0)
  33.  
  34. /* Initialize a string descriptor (struct dsc$descriptor_s) for a
  35.    NUL-terminated string.  S is a pointer to the string; the length
  36.    is determined by calling strlen(). */
  37.  
  38. #define INIT_DSC_CSTRING(dsc, s) INIT_DSC_S(dsc, s, strlen(s))
  39. #endif
  40.  
  41. /*
  42.   copy 'from' to 'to' up to but not including 'upto'
  43.   return 0 if eos on from
  44.   return 1 if upto found
  45.  
  46.   return 'to' at last char + 1
  47.   return 'from' at match + 1 or eos if no match
  48.  
  49.   if as_dir == 1, change all '.' to '_'
  50.   else change all '.' but the last to '_'
  51. */
  52.  
  53. static int
  54. copyto (char **to, char **from, char upto, int as_dir)
  55. {
  56.   char *s;
  57.  
  58.   s = strrchr (*from, '.');
  59.  
  60.   while (**from)
  61.     {
  62.       if (**from == upto)
  63.     {
  64.       do
  65.         {
  66.           (*from)++;
  67.         }
  68.       while (**from == upto);
  69.       return 1;
  70.     }
  71.       if (**from == '.')
  72.     {
  73.       if ((as_dir == 1)
  74.           || (*from != s))
  75.         **to = '_';
  76.       else
  77.         **to = '.';
  78.     }
  79.       else
  80.     {
  81.       if (islower (**from))
  82.         **to = toupper (**from);
  83.       else
  84.         **to = **from;
  85.     }
  86.       (*to)++;
  87.       (*from)++;
  88.     }
  89.  
  90.   return 0;
  91. }
  92.  
  93.  
  94. /*
  95.   get translation of logical name
  96.  
  97. */
  98.  
  99. static char *
  100. trnlog (char *name)
  101. {
  102.   int stat;
  103.   static char reslt[1024];
  104.   $DESCRIPTOR (reslt_dsc, reslt);
  105.   short resltlen;
  106.   struct dsc$descriptor_s name_dsc;
  107.   char *s;
  108.  
  109.   INIT_DSC_CSTRING (name_dsc, name);
  110.  
  111.   stat = lib$sys_trnlog (&name_dsc, &resltlen, &reslt_dsc);
  112.  
  113.   if ((stat&1) == 0)
  114.     {
  115.       return "";
  116.     }
  117.   if (stat == SS$_NOTRAN)
  118.     {
  119.       return "";
  120.     }
  121.   reslt[resltlen] = '\0';
  122.  
  123.   s = (char *)malloc (resltlen+1);
  124.   if (s == 0)
  125.     return "";
  126.   strcpy (s, reslt);
  127.   return s;
  128. }
  129.  
  130. enum namestate { N_START, N_DEVICE, N_OPEN, N_DOT, N_CLOSED, N_DONE };
  131.  
  132. /*
  133.   convert unix style name to vms style
  134.   type = 0 -> name is a full name (directory and filename part)
  135.   type = 1 -> name is a directory
  136.   type = 2 -> name is a filename without directory
  137.  
  138.   The following conversions are applied
  139.             (0)        (1)            (2)
  140.     input        full name    dir name        file name
  141.  
  142. 1    ./        <cwd>        []            <current directory>.dir
  143. 2    ../        <home of cwd>    <home of cwd>        <home of cwd>.dir
  144.  
  145. 3    //        <dev of cwd>:    <dev of cwd>:[000000]    <dev of cwd>:000000.dir
  146. 4    //a        a:        a:            a:
  147. 5    //a/        a:        a:            a:000000.dir
  148.  
  149. 9    /        [000000]    [000000]        000000.dir
  150. 10    /a        [000000]a    [a]            [000000]a
  151. 11    /a/        [a]        [a]            [000000]a.dir
  152. 12    /a/b        [a]b        [a.b]            [a]b
  153. 13    /a/b/        [a.b]        [a.b]            [a]b.dir
  154. 14    /a/b/c        [a.b]c        [a.b.c]            [a.b]c
  155. 15    /a/b/c/        [a.b.c]        [a.b.c]            [a.b]c.dir
  156.  
  157. 16    a        a        [.a]            a
  158. 17    a/        [.a]        [.a]            a.dir
  159. 18    a/b        [.a]b        [.a.b]            [.a]b
  160. 19    a/b/        [.a.b]        [.a.b]            [.a]b.dir
  161. 20    a/b/c        [.a.b]c        [.a.b.c]        [.a.b]c
  162. 21    a/b/c/        [.a.b.c]    [.a.b.c]        [.a.b]c.dir
  163.  
  164. 22    a.b.c        a_b.c        [.a_b_c]        a_b_c.dir
  165.  
  166. 23    [x][y]z        [x.y]z        [x.y]z            [x.y]z
  167. 24    [x][.y]z    [x.y]z        [x.y]z            [x.y]z
  168.  
  169. 25  filenames with '$'  are left unchanged if they contain no '/'
  170. 25  filenames with ':' are left unchanged
  171. 26  filenames with a single pair of '[' ']' are left unchanged
  172.  
  173.   the input string is not written to
  174. */
  175.  
  176. char *
  177. vmsify (name, type)
  178.     char *name;
  179.     int type;
  180. {
  181. /* max 255 device
  182.    max 39 directory
  183.    max 39 filename
  184.    max 39 filetype
  185.    max 5 version
  186. */
  187. #define MAXPATHLEN 512
  188.  
  189.   enum namestate nstate;
  190.   static char vmsname[MAXPATHLEN+1];
  191.   char *fptr;
  192.   char *vptr;
  193.   char *s,*s1;
  194.   int as_dir;
  195.   int count;
  196.  
  197.   if (name == 0)
  198.     return 0;
  199.   fptr = name;
  200.   vptr = vmsname;
  201.   nstate = N_START;
  202.  
  203.   /* case 25a */
  204.  
  205.   s = strpbrk (name, "$:");
  206.   if (s != 0)
  207.     {
  208.       if (*s == '$')
  209.     {
  210.       if (strchr (name, '/') == 0)
  211.         {
  212.           return name;
  213.         }
  214.     }
  215.       else
  216.     {
  217.       return name;
  218.     }
  219.     }
  220.  
  221.   /* case 26 */
  222.  
  223.   s = strchr (name, '[');
  224.  
  225.   if (s != 0)
  226.     {
  227.       s1 = strchr (s+1, '[');
  228.       if (s1 == 0)
  229.     {
  230.       return name;            /* single [, keep unchanged */
  231.     }
  232.       s1--;
  233.       if (*s1 != ']')
  234.     {
  235.       return name;            /* not ][, keep unchanged */
  236.     }
  237.  
  238.       /* we have ][ */
  239.  
  240.       s = name;
  241.  
  242.       /* s  -> starting char
  243.      s1 -> ending ']'  */
  244.  
  245.       do
  246.     {
  247.       strncpy (vptr, s, s1-s);    /* copy up to but not including ']' */
  248.       vptr += s1-s;
  249.       if (*s1 == 0)
  250.         break;
  251.       s = s1 + 1;            /* s -> char behind ']' */
  252.       if (*s != '[')        /* was '][' ? */
  253.         break;            /* no, last ] found, exit */
  254.       s++;
  255.       if (*s != '.')
  256.         *vptr++ = '.';
  257.       s1 = strchr (s, ']');
  258.       if (s1 == 0)            /* no closing ] */
  259.         s1 = s + strlen (s);
  260.     }
  261.       while (1);
  262.  
  263.       *vptr++ = ']';
  264.  
  265.       fptr = s;
  266.  
  267.     }
  268.  
  269.   else        /* no [ in name */
  270.  
  271.     {
  272.  
  273.       int state;
  274.       int rooted = 1;    /* flag if logical is rooted, else insert [000000] */
  275.  
  276.       state = 0;
  277.  
  278.       do
  279.     {
  280.  
  281.       switch (state)
  282.     {
  283.       case 0:                /* start of loop */
  284.         if (*fptr == '/')
  285.           {
  286.         fptr++;
  287.         state = 1;
  288.           }
  289.         else if (*fptr == '.')
  290.           {
  291.         fptr++;
  292.         state = 10;
  293.           }
  294.         else
  295.           state = 2;
  296.         break;
  297.  
  298.       case 1:                /* '/' at start */
  299.         if (*fptr == '/')
  300.           {
  301.         fptr++;
  302.         state = 3;
  303.           }
  304.         else
  305.           state = 4;
  306.         break;
  307.  
  308.       case 2:                /* no '/' at start */
  309.         s = strchr (fptr, '/');
  310.         if (s == 0)            /* no '/' (16) */
  311.           {
  312.         if (type == 1)
  313.           {
  314.             strcpy (vptr, "[.");
  315.             vptr += 2;
  316.           }
  317.         copyto (&vptr, &fptr, 0, (type==1));
  318.         if (type == 1)
  319.           *vptr++ = ']';
  320.         state = -1;
  321.           }
  322.         else            /* found '/' (17..21) */
  323.           {
  324.         if ((type == 2)
  325.             && (*(s+1) == 0))    /* 17(2) */
  326.           {
  327.             copyto (&vptr, &fptr, '/', 1);
  328.             state = 7;
  329.           }
  330.         else
  331.           {
  332.             strcpy (vptr, "[.");
  333.             vptr += 2;
  334.             copyto (&vptr, &fptr, '/', 1);
  335.             nstate = N_OPEN;
  336.             state = 9;
  337.           }
  338.           }
  339.         break;
  340.  
  341.       case 3:                /* '//' at start */
  342.         while (*fptr == '/')    /* collapse all '/' */
  343.           fptr++;
  344.         if (*fptr == 0)        /* just // */
  345.           {
  346.         char cwdbuf[MAXPATHLEN+1];
  347.  
  348.         s1 = getcwd(cwdbuf, MAXPATHLEN);
  349.         if (s1 == 0)
  350.           {
  351.             return "";        /* FIXME, err getcwd */
  352.           }
  353.         s = strchr (s1, ':');
  354.         if (s == 0)
  355.           {
  356.             return "";        /* FIXME, err no device */
  357.           }
  358.         strncpy (vptr, s1, s-s1+1);
  359.         vptr += s-s1+1;
  360.         state = -1;
  361.         break;
  362.           }
  363.  
  364.         s = vptr;
  365.  
  366.         if (copyto (&vptr, &fptr, '/', 1) == 0)    /* copy device part */
  367.           {
  368.         *vptr++ = ':';
  369.         state = -1;
  370.         break;
  371.           }
  372.         *vptr = ':';
  373.         nstate = N_DEVICE;
  374.         if (*fptr == 0)    /* just '//a/' */
  375.           {
  376.         strcpy (vptr+1, "[000000]");
  377.         vptr += 9;
  378.         state = -1;
  379.         break;
  380.           }
  381.         *vptr = 0;
  382.                 /* check logical for [000000] insertion */
  383.         s1 = trnlog (s);
  384.         if (*s1 != 0)
  385.           {            /* found translation */
  386.         char *s2;
  387.         for (;;)    /* loop over all nested logicals */
  388.           {
  389.             s2 = s1 + strlen (s1) - 1;
  390.             if (*s2 == ':')    /* translation ends in ':' */
  391.               {
  392.             s2 = trnlog (s1);
  393.             free (s1);
  394.             if (*s2 == 0)
  395.               {
  396.                 rooted = 0;
  397.                 break;
  398.               }
  399.             s1 = s2;
  400.             continue;    /* next iteration */
  401.               }
  402.             if (*s2 == ']')    /* translation ends in ']' */
  403.               {
  404.             if (*(s2-1) == '.')    /* ends in '.]' */
  405.               {
  406.                 if (strncmp (fptr, "000000", 6) != 0)
  407.                   rooted = 0;
  408.               }
  409.             else
  410.               {
  411.                 strcpy (vmsname, s1);
  412.                 s = strchr (vmsname, ']');
  413.                 *s = '.';
  414.                 nstate = N_DOT;
  415.                 vptr = s;
  416.               }
  417.               }
  418.             break;
  419.           }
  420.         free (s1);
  421.           }
  422.         else
  423.           rooted = 0;
  424.  
  425.         if (*vptr == 0)
  426.           {
  427.         nstate = N_DEVICE;
  428.             *vptr++ = ':';
  429.           }
  430.         else
  431.           vptr++;
  432.  
  433.         if (rooted == 0)
  434.           {
  435.             strcpy (vptr, "[000000.");
  436.         vptr += 8;
  437.         s1 = vptr-1;
  438.         nstate = N_DOT;
  439.           }
  440.         else
  441.           s1 = 0;
  442.  
  443.     /* s1-> '.' after 000000 or NULL */
  444.  
  445.         s = strchr (fptr, '/');
  446.         if (s == 0)
  447.           {                /* no next '/' */
  448.         if (*(vptr-1) == '.')
  449.           *(vptr-1) = ']';
  450.         else if (rooted == 0)
  451.           *vptr++ = ']';
  452.         copyto (&vptr, &fptr, 0, (type == 1));
  453.         state = -1;
  454.         break;
  455.           }
  456.         else
  457.           {
  458.         while (*(s+1) == '/')    /* skip multiple '/' */
  459.           s++;
  460.           }
  461.  
  462.         if ((rooted != 0)
  463.             && (*(vptr-1) != '.'))
  464.           {
  465.         *vptr++ = '[';
  466.         nstate = N_DOT;
  467.           }
  468.         else
  469.           if ((nstate == N_DOT)
  470.          && (s1 != 0)
  471.          && (*(s+1) == 0))
  472.         {
  473.           if (type == 2)
  474.             {
  475.               *s1 = ']';
  476.               nstate = N_CLOSED;
  477.             }
  478.         }
  479.         state = 9;
  480.         break;
  481.  
  482.       case 4:                /* single '/' at start (9..15) */
  483.         if (*fptr == 0)
  484.           state = 5;
  485.         else
  486.           state = 6;
  487.         break;
  488.  
  489.       case 5:                /* just '/' at start (9) */
  490.         if (type != 2)
  491.           {
  492.             *vptr++ = '[';
  493.         nstate = N_OPEN;
  494.           }
  495.         strcpy (vptr, "000000");
  496.         vptr += 6;
  497.         if (type == 2)
  498.           state = 7;
  499.         else
  500.           state = 8;
  501.         break;
  502.  
  503.       case 6:                /* chars following '/' at start 10..15 */
  504.         *vptr++ = '[';
  505.         nstate = N_OPEN;
  506.         s = strchr (fptr, '/');
  507.         if (s == 0)            /* 10 */
  508.           {
  509.         if (type != 1)
  510.           {
  511.             strcpy (vptr, "000000]");
  512.             vptr += 7;
  513.           }
  514.         copyto (&vptr, &fptr, 0, (type == 1));
  515.         if (type == 1)
  516.           {
  517.             *vptr++ = ']';
  518.           }
  519.         state = -1;
  520.           }
  521.         else            /* 11..15 */
  522.           {
  523.         if ( (type == 2)
  524.            && (*(s+1) == 0))    /* 11(2) */
  525.           {
  526.             strcpy (vptr, "000000]");
  527.             nstate = N_CLOSED;
  528.             vptr += 7;
  529.           }
  530.         copyto (&vptr, &fptr, '/', (*(vptr-1) != ']'));
  531.         state = 9;
  532.           }
  533.         break;
  534.  
  535.       case 7:                /* add '.dir' and exit */
  536.         if ((nstate == N_OPEN)
  537.         || (nstate == N_DOT))
  538.           {
  539.         s = vptr-1;
  540.         while (s > vmsname)
  541.           {
  542.             if (*s == ']')
  543.               {
  544.             break;
  545.               }
  546.             if (*s == '.')
  547.               {
  548.             *s = ']';
  549.             break;
  550.               }
  551.             s--;
  552.           }
  553.           }
  554.         strcpy (vptr, ".dir");
  555.         vptr += 4;
  556.         state = -1;
  557.         break;
  558.  
  559.       case 8:                /* add ']' and exit */
  560.         *vptr++ = ']';
  561.         state = -1;
  562.         break;
  563.  
  564.       case 9:                /* 17..21, fptr -> 1st '/' + 1 */
  565.         if (*fptr == 0)
  566.           {
  567.         if (type == 2)
  568.           {
  569.             state = 7;
  570.           }
  571.         else
  572.           state = 8;
  573.         break;
  574.           }
  575.         s = strchr (fptr, '/');
  576.         if (s == 0)
  577.           {
  578.         if (type != 1)
  579.           {
  580.             if (nstate == N_OPEN)
  581.               {
  582.             *vptr++ = ']';
  583.             nstate = N_CLOSED;
  584.               }
  585.             as_dir = 0;
  586.           }
  587.         else
  588.           {
  589.             if (nstate == N_OPEN)
  590.               {
  591.             *vptr++ = '.';
  592.             nstate = N_DOT;
  593.               }
  594.             as_dir = 1;
  595.           }
  596.           }
  597.         else
  598.           {
  599.         while (*(s+1) == '/')
  600.           s++;
  601.         if ( (type == 2)
  602.             && (*(s+1) == 0))        /* 19(2), 21(2)*/
  603.           {
  604.             if (nstate != N_CLOSED)
  605.               {
  606.             *vptr++ = ']';
  607.             nstate = N_CLOSED;
  608.               }
  609.             as_dir = 1;
  610.           }
  611.         else
  612.           {
  613.             if (nstate == N_OPEN)
  614.               {
  615.             *vptr++ = '.';
  616.             nstate = N_DOT;
  617.               }
  618.             as_dir = 1;
  619.           }
  620.           }
  621.         if ( (*fptr == '.')            /* check for '..' or '../' */
  622.         && (*(fptr+1) == '.')
  623.         && ((*(fptr+2) == '/')
  624.             || (*(fptr+2) == 0)) )
  625.           {
  626.         fptr += 2;
  627.         if (*fptr == '/')
  628.           {
  629.             do
  630.               {
  631.             fptr++;
  632.               }
  633.             while (*fptr == '/');
  634.           }
  635.         else if (*fptr == 0)
  636.           type = 1;
  637.         vptr--;                /* vptr -> '.' or ']' */
  638.         s1 = vptr;
  639.         for (;;)
  640.           {
  641.             s1--;
  642.             if (*s1 == '.')        /* one back */
  643.               {
  644.             vptr = s1;
  645.             nstate = N_OPEN;
  646.             break;
  647.               }
  648.             if (*s1 == '[')        /* top level reached */
  649.               {
  650.             if (*fptr == 0)
  651.               {
  652.                 strcpy (s1, "[000000]");
  653.                 vptr = s1 + 8;
  654.                 nstate = N_CLOSED;
  655.                 s = 0;
  656.                 break;
  657.               }
  658.             else
  659.               {
  660.                 vptr = s1+1;
  661.                 nstate = N_OPEN;
  662.                 break;
  663.               }
  664.               } 
  665.           }
  666.           }
  667.         else
  668.           {
  669.         copyto (&vptr, &fptr, '/', as_dir);
  670.         if (nstate == N_DOT)
  671.           nstate = N_OPEN;
  672.           }
  673.         if (s == 0)
  674.           {                    /* 18,20 */
  675.         if (type == 1)
  676.           *vptr++ = ']';
  677.         state = -1;
  678.           }
  679.         else
  680.           {
  681.         if (*(s+1) == 0)
  682.           {
  683.             if (type == 2)        /* 19,21 */
  684.               {
  685.                 state = 7;
  686.               }
  687.             else
  688.               {
  689.             *vptr++ = ']';
  690.             state = -1;
  691.               }
  692.           }
  693.           }
  694.         break;
  695.  
  696.       case 10:                /* 1,2 first is '.' */
  697.         if (*fptr == '.')
  698.           {
  699.         fptr++;
  700.         state = 11;
  701.           }
  702.         else
  703.           state = 12;
  704.         break;
  705.  
  706.       case 11:                /* 2, '..' at start */
  707.         count = 1;
  708.         if (*fptr != 0)
  709.           {
  710.         if (*fptr != '/')        /* got ..xxx */
  711.           {
  712.             return name;
  713.           }
  714.         do                /* got ../ */
  715.           {
  716.             fptr++;
  717.             while (*fptr == '/') fptr++;
  718.             if (*fptr != '.')
  719.               break;
  720.             if (*(fptr+1) != '.')
  721.               break;
  722.             fptr += 2;
  723.             if ((*fptr == 0)
  724.             || (*fptr == '/'))
  725.               count++;
  726.           }
  727.         while (*fptr == '/');
  728.           }
  729.         {                    /* got '..' or '../' */
  730.           char cwdbuf[MAXPATHLEN+1];
  731.  
  732.           s1 = getcwd(cwdbuf, MAXPATHLEN);
  733.           if (s1 == 0)
  734.         {
  735.           return "";        /* FIXME, err getcwd */
  736.         }
  737.           strcpy (vptr, s1);
  738.           s = strchr (vptr, ']');
  739.           if (s != 0)
  740.         {
  741.           nstate = N_OPEN;
  742.           while (s > vptr)
  743.             {
  744.               s--;
  745.               if (*s == '[')
  746.             {
  747.               s++;
  748.               strcpy (s, "000000]");
  749.               state = -1;
  750.               break;
  751.             }
  752.               else if (*s == '.')
  753.             {
  754.               if (--count == 0)
  755.                 {
  756.                   if (*fptr == 0)    /* had '..' or '../' */
  757.                 {
  758.                   *s++ = ']';
  759.                   state = -1;
  760.                 }
  761.                   else            /* had '../xxx' */
  762.                 {
  763.                   state = 9;
  764.                 }
  765.                   *s = 0;
  766.                   break;
  767.                 }
  768.             }
  769.             }
  770.         }
  771.           vptr += strlen (vptr);
  772.         }
  773.         break;
  774.  
  775.       case 12:                /* 1, '.' at start */
  776.         if (*fptr != 0)
  777.           {
  778.         if (*fptr != '/')
  779.           {
  780.             return name;
  781.           }
  782.         fptr++;
  783.           }
  784.  
  785.         {
  786.           char cwdbuf[MAXPATHLEN+1];
  787.  
  788.           s1 = getcwd(cwdbuf, MAXPATHLEN);
  789.           if (s1 == 0)
  790.         {
  791.           return "";        /*FIXME, err getcwd */
  792.         }
  793.           strcpy (vptr, s1);
  794.           if (*fptr == 0)
  795.         {
  796.           state = -1;
  797.           break;
  798.         }
  799.           else
  800.         {
  801.           s = strchr (vptr, ']');
  802.           if (s == 0)
  803.             {
  804.               state = -1;
  805.               break;
  806.             }
  807.           *s = 0;
  808.           nstate = N_OPEN;
  809.           vptr += strlen (vptr);
  810.           state = 9;
  811.         }
  812.         }
  813.         break;
  814.     }
  815.  
  816.     }
  817.       while (state > 0);
  818.       
  819.  
  820.     }
  821.  
  822.  
  823.   /* directory conversion done
  824.      fptr -> filename part of input string
  825.      vptr -> free space in vmsname
  826.   */
  827.  
  828.   *vptr++ = 0;
  829.  
  830.   return vmsname;
  831. }
  832.  
  833.  
  834.  
  835. /*
  836.   convert from vms-style to unix-style
  837.  
  838.   dev:[dir1.dir2]    //dev/dir1/dir2/
  839. */
  840.  
  841. char *
  842. unixify (char *name)
  843. {
  844.   static char piece[512];
  845.   char *s, *p;
  846.  
  847.   if (strchr (name, '/') != 0)        /* already in unix style */
  848.     return name;
  849.  
  850.   p = piece;
  851.   *p = 0;
  852.  
  853.   /* device part */
  854.  
  855.   s = strchr (name, ':');
  856.  
  857.   if (s != 0)
  858.     {
  859.       *s = 0;
  860.       *p++ = '/';
  861.       *p++ = '/';
  862.       strcpy (p, name);
  863.       p += strlen (p);
  864.       *s = ':';
  865.     }
  866.  
  867.   /* directory part */
  868.  
  869.   *p++ = '/';
  870.   s = strchr (name, '[');
  871.  
  872.   if (s != 0)
  873.     {
  874.       s++;
  875.       switch (*s)
  876.         {
  877.       case ']':        /* [] */
  878.         strcat (p, "./");
  879.         break;
  880.       case '-':        /* [- */
  881.         strcat (p, "../");
  882.         break;
  883.       case '.':
  884.         strcat (p, "./");    /* [. */
  885.         break;
  886.       default:
  887.         s--;
  888.         break;
  889.         }
  890.       s++;
  891.       while (*s)
  892.         {
  893.       if (*s == '.')
  894.         *p++ = '/';
  895.       else
  896.         *p++ = *s;
  897.       s++;
  898.       if (*s == ']')
  899.         {
  900.           s++;
  901.           break;
  902.         }
  903.         }
  904.       if (*s != 0)        /* more after ']' ?? */
  905.         {
  906.       if (*(p-1) != '/')
  907.         *p++ = '/';
  908.       strcpy (p, s);        /* copy it anyway */
  909.         }
  910.     }
  911.  
  912.   else        /* no '[' anywhere */
  913.  
  914.     {
  915.       *p++ = 0;
  916.     }
  917.  
  918.   /* force end with '/' */
  919.  
  920.   if (*(p-1) != '/')
  921.     *p++ = '/';
  922.   *p = 0;
  923.  
  924.   return piece;
  925. }
  926.  
  927. /* EOF */
  928.